#include <iostream>
#include <string>
#include <ctime>
#include "UnitTest.h"
#include "CircularBuffer.h"
#include "BufferErrorPolicies.h"
#include "UnitTestPolicies.h"

int main(int argc, char* argv[]) 
{
	CircularBuffer<int> defaultBufferTest(100);
	std::cout << "Test buffer empty" << std::endl;
	try
	{
		defaultBufferTest.front();
	}
	catch(ReadErrorPolicyException<int>::Exception& e)
	{
		std::cout << "\tReadErrorPolicyException<int>::Exception is expected: \n\t" << e.what() << std::endl;
	}
	std::cout << "Test buffer empty. PASSED!" << std::endl;
	
	std::cout << "Test Insert and pop method" << std::endl;
	try 
	{
		for (size_t i = 0; i < defaultBufferTest.size(); ++i)
			defaultBufferTest.push_back(i);

		UnitTest<int>::testMethod(defaultBufferTest.size(), 100);
	}
	catch(WrongResultException& e)
	{
		std::cout << e.what() << std::endl;
	}

	try
	{
		for (size_t i = 0; i < defaultBufferTest.size(); ++i)
			UnitTest<int>::testMethod(defaultBufferTest[i], i);
	
		for (size_t i = 0; i < defaultBufferTest.size(); ++i)
		{
			UnitTest<int>::testMethod(defaultBufferTest.front(), i);
			defaultBufferTest.pop_front();
		}
		//insert a 101th chunk should be at front due to the size of 100 ;)
		defaultBufferTest.push_back(101);
		UnitTest<int, TestPolicyAssert>::testMethod(defaultBufferTest.front(), 101);
	}
	catch (WrongResultException& e)
	{
		std::cout << e.what() << std::endl;
	}
	std::cout << "Test Insert and pop method. PASSED!" << std::endl;

	std::cout << "Test default value return" << std::endl; 
	ReadErrorPolicyDefaultValue<std::string>::defaultValue = "default_value";
	CircularBuffer<std::string, WriteErrorPolicyOverride, ReadErrorPolicyDefaultValue> defaultValueTest(2);
	
	defaultValueTest.push_back("stuff");
	defaultValueTest.pop_front();
	try
	{
		UnitTest<std::string>::testMethod(defaultValueTest.front(), "default_value");
	}
	catch (WrongResultException& e)
	{
		std::cout << e.what() << std::endl;
	}
	std::cout << "Test default value return. PASSED!" << std::endl; 

	std::cout << "Test override oldest." << std::endl; 
	try 
	{
		defaultValueTest.push_back("0");
		defaultValueTest.push_back("1");
		defaultValueTest.push_back("2"); // the oldest value is wiped out here

		UnitTest<std::string>::testMethod(defaultValueTest.front(), "1");
	}
	catch(WrongResultException& e)
	{
		std::cout << e.what() << std::endl;
	}
	std::cout << "Test override oldest. PASSED!" << std::endl; 

	std::cout << "Test exception if full." << std::endl; 
	CircularBuffer<std::string, WriteErrorPolicyException, ReadErrorPolicyDefaultValue> exceptionIsFullBuffer(2);
	try
	{
		exceptionIsFullBuffer.push_back("0");
		exceptionIsFullBuffer.push_back("1");
		exceptionIsFullBuffer.push_back("2");
	}
	catch(WriteErrorPolicyException<std::string>::Exception& e)
	{	
		std::cout << "\tWriteErrorPolicyException<std::string>::Exception is expected: \n\t" << e.what() << std::endl;
	}
	std::cout << "Test exception if full. PASSED" << std::endl; 

	return 0;
}